package com.haoyun.common.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by twg on 2018/2/22.
 * 非RestFul请求统一异常处理
 */
@Slf4j
@Component
public class RequestHandlerExceptionResolverWrapper extends DefaultHandlerExceptionResolver {
    @Value("${server.error.view:error}")
    private String PATH = "/error";

    @Override
    public ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        log.info("Handling of [{}] resulted in Exception.", ex);
        try {
            if (ex instanceof RuntimeException) {
                return handleRequestMethod((RuntimeException) ex, request, response, handler);
            }
        } catch (Exception handlerException) {
            if (log.isWarnEnabled()) {
                log.warn("Handling of [" + ex.getClass().getName() + "] resulted in Exception", handlerException);
            }
        }
        return new ModelAndView();
    }

    private ModelAndView handleRequestMethod(RuntimeException ex,
                                             HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
        Map<String, Object> model = new HashMap<String, Object>();
        HttpStatus status = getStatus(request);
        response.setStatus(status.value());
        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex.getMessage());

        model.put("status", status.value());
        model.put("message", ex.getMessage());
        if (PATH.startsWith(File.separator)) {
            return new ModelAndView(String.format("%s%s%d", PATH.substring(PATH.lastIndexOf(File.separator)), File.separator, status.value()), model);
        }
        return new ModelAndView(String.format("%s%s%d", PATH, File.separator, status.value()), model);
    }

    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request
                .getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        try {
            return HttpStatus.valueOf(statusCode);
        } catch (Exception ex) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
    }
}
